import fs from 'fs/promises';
import { accessSync, unlinkSync, existsSync, mkdirSync } from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';

export const dirname = (url) =>{
  const __filename = fileURLToPath(url);
  return path.dirname(__filename);
}


/**
 * 获取指定路径的文件树结构
 * 
 * @param {string} basePath - 要扫描的基础路径
 * @param {boolean} [deep=true] - 是否深度遍历子目录
 * @returns {Promise<Array<Object>>} 文件树数组，每个元素包含文件/目录信息
 * @returns {string} return[].name - 名称
 * @returns {string} return[].path - 完整路径
 * @returns {string} return[].relativePath - 相对于APP_PATH的路径
 * @returns {'directory'|'file'} return[].type - 类型（目录或文件）
 * @returns {number} return[].size - 大小（字节）
 * @returns {Date} return[].modified - 最后修改时间
 * @returns {number} return[].depth - 深度
 * @returns {Array<Object>} [return[].children] - 子目录内容（仅目录有）
 * @throws {Error} 当路径不存在或没有访问权限时抛出错误
 */
export const getFileTree = async (basePath, deep = true) => {
  try {
    const stats = await fs.stat(basePath);
    if (!stats.isDirectory()) {
      return [];
    }

    const items = await fs.readdir(basePath);
    const tree = [];

    for (const item of items) {
      const itemPath = path.join(basePath, item);
      const itemStats = await fs.stat(itemPath);

      const treeItem = {
        name: item,
        path: itemPath,
        relativePath: path.relative(ROOT_PATH, itemPath),
        type: itemStats.isDirectory() ? 'directory' : 'file',
        size: itemStats.size,
        modified: itemStats.mtime,
        depth: itemPath.split(path.sep).length - path.resolve(ROOT_PATH).split(path.sep).length
      };

      if (treeItem.type === 'directory' && deep) {
        treeItem.children = await getFileTree(itemPath, deep);
      }

      tree.push(treeItem);
    }

    // 排序：文件夹在前，文件在后，名称按字母顺序排列
    return tree.sort((a, b) => {
      if (a.type === b.type) {
        return a.name.localeCompare(b.name, undefined, { sensitivity: 'base' });
      }
      return a.type === 'directory' ? -1 : 1;
    });
  } catch (error) {
    console.error(`获取文件树失败: ${basePath}`, error);
    throw error;
  }
};

/**
 * 读取文件内容（UTF-8编码）
 * 
 * @param {string} filePath - 要读取的文件路径
 * @returns {Promise<string>} 文件内容字符串
 * @throws {Error} 当文件不存在、无法读取或不是文件时抛出错误
 */
export const readFileContent = async (filePath) => {
  try {
    // 先检查路径是否安全
    if (!isPathSafe(filePath,APP_PATH)  && !isPathSafe(filePath,ROOT_PATH)) {
      throw new Error(`路径不安全: ${filePath}`);
    }
    
    // 检查是否为文件
    const stats = await fs.stat(filePath);
    if (!stats.isFile()) {
      throw new Error(`不是文件: ${filePath}`);
    }
    
    return await fs.readFile(filePath, 'utf8');
  } catch (error) {
    console.error(`读取文件失败: ${filePath}`, error);
    throw error;
  }
};

/**
 * 保存内容到文件（UTF-8编码）
 * 
 * @param {string} filePath - 要保存的文件路径
 * @param {string} content - 要写入的内容
 * @returns {Promise<void>} 无返回值
 * @throws {Error} 当路径不安全、无法写入或发生其他错误时抛出错误
 */
export const saveFileContent = async (filePath, content) => {
  try {
    // 先检查路径是否安全
    if (!isPathSafe(filePath,APP_PATH)  && !isPathSafe(filePath,ROOT_PATH)) {
      throw new Error(`路径不安全: ${filePath}`);
    }
    
    // 确保目录存在
    const dirname = path.dirname(filePath);
    await fs.mkdir(dirname, { recursive: true });
    
    // 写入文件
    await fs.writeFile(filePath, content, 'utf8');
  } catch (error) {
    console.error(`保存文件失败: ${filePath}`, error);
    throw error;
  }
};

/**
 * 验证路径是否在基础路径范围内（防止路径遍历攻击）
 * 
 * @param {string} requestedPath - 要验证的路径
 * @param {string} basePath - 基础路径，requestedPath必须在此路径下
 * @returns {boolean} 如果路径安全则返回true，否则返回false
 */
export const isPathSafe = (requestedPath, basePath) => {
  const resolvedRequestedPath = path.resolve(requestedPath);
  const resolvedBasePath = path.resolve(basePath);
  // 检查请求的路径是否以基础路径为前缀
  return resolvedRequestedPath.startsWith(resolvedBasePath);
};

/**
 * 删除指定路径的图片文件
 * 
 * @param {string} link - 图片文件的路径
 * @returns {boolean} 成功删除返回true，否则返回false
 * @description 同步操作，会检查文件是否存在后再删除
 */
export function delImg(link) {
  try {
    // 先检查路径是否安全
    if (!isPathSafe(link, APP_PATH)) {
      console.error(`路径不安全: ${link}`);
      return false;
    }
    
    // 检查文件是否存在
    accessSync(link);
    
    // 删除文件
    unlinkSync(link);
    return true;
  } catch (err) {
    console.error(`删除图片失败: ${link}`, err);
    return false;
  }
}

/**
 * 递归创建目录（同步操作）
 * 
 * @param {string} dirname - 要创建的目录路径
 * @returns {boolean} 成功创建或目录已存在返回true，否则返回false
 * @description 类似于mkdir -p命令，会创建所有不存在的父目录
 */
export function mkdirsSync(dirname) {
  try {
    // 先检查路径是否安全
    if (!isPathSafe(dirname, APP_PATH)) {
      console.error(`路径不安全: ${dirname}`);
      return false;
    }
    
    if (existsSync(dirname)) {
      return true;
    }
    
    // 递归创建父目录
    const parentDir = path.dirname(dirname);
    if (mkdirsSync(parentDir)) {
      mkdirSync(dirname);
      return true;
    }
    
    return false;
  } catch (err) {
    console.error(`创建目录失败: ${dirname}`, err);
    return false;
  }
}


export default {
  mkdirsSync,
  delImg,
  isPathSafe,
  saveFileContent,
  readFileContent,
  getFileTree,
}